Trying to get to the bottom of the differences between my and Ian’s prediction analyses.

Problem: In his analyses Ian found very low cross-validated \(R^2\) values when predicting demographic factors using the task ontology. In my analyses using factors of EZ DDM variables and raw RT’s and accuracies I found relationships that were >0.

Approach: Our analyses differ in multiple aspects both in the predicted data (DV data) and predictor data (IV data) so we checked each of them to find where the difference may lay.

1. DV data

We both calculated 9 factor solutions for the demographic items separately. our factor scores are essentially the same as can be seen in the last plot here.

Still, checked whether there were any differences predicting his or my factor scores.

The plot below suggests
- There are no systematic differences depending on the DV data
- The largest difference is between predicting using n=522 or n=150
- Raw measures seem to have some >0 association too

helper_func_path = 'https://raw.githubusercontent.com/zenkavi/SRO_Retest_Analyses/master/code/helper_functions/'

eval(parse(text = getURL(paste0(helper_func_path,'sem.R'), ssl.verifypeer = FALSE)))

ddm_workspace_scripts = 'https://raw.githubusercontent.com/zenkavi/SRO_DDM_Analyses/master/code/workspace_scripts/'

eval(parse(text = getURL(paste0(ddm_workspace_scripts,'ddm_measure_labels.R'), ssl.verifypeer = FALSE)))

input_path='/Users/zeynepenkavi/Dropbox/PoldrackLab/SRO_DDM_Analyses/input/'

out_device = "jpeg"

fig_path = '/Users/zeynepenkavi/Dropbox/PoldrackLab/SRO_DDM_Analyses/output/figures/'
iv_dfs = c("ez_t1_522_fa_3_scores", "ez_t1_fa_3_scores", "res_clean_test_data_raw", "res_clean_test_data_ez")
dv_dfs = c('ian_demog_scores', 'demog_fa_scores_t1')

out = data.frame()

for(iv_data in iv_dfs){
  for(dv_data in dv_dfs){
    file_name = paste0(input_path,'prediction/pred_out_', iv_data,'_', dv_data, '.csv')
    
    d = read.csv(file_name) 
    
    if(iv_data %in% c("ez_t1_522_fa_3_scores", "ez_t1_fa_3_scores")){
      d = d %>%
        mutate(RsquaredSE = RsquaredSD/sqrt(10),
         iv=as.character(iv),
         dv = as.character(dv),
         iv_data = as.character(iv_data),
         dv_data = as.character(dv_data)) %>%
  select(dv, iv, Rsquared, RsquaredSE, iv_data, dv_data)
    }
    
    if(iv_data =="res_clean_test_data_raw"){
      d = d %>%
        mutate(iv=as.character(iv),
         iv=gsub(".ReflogTr", "",iv),
         iv=gsub(".logTr", "",iv)) %>% 
  left_join(measure_labels %>% select(dv, rt_acc) %>% rename(iv=dv), by="iv") %>%
  group_by(dv, rt_acc) %>%
  summarise(RsquaredSE = sem(Rsquared),
            Rsquared = mean(Rsquared),
            iv_data = as.character(unique(iv_data)),
            dv_data = as.character(unique(dv_data))) %>%
  rename(iv = rt_acc) %>%
  ungroup() %>%
  mutate(dv = as.character(dv)) %>%
  select(dv, iv, Rsquared, RsquaredSE, iv_data, dv_data)
    }
    
    if(iv_data == "res_clean_test_data_ez"){
      d = d%>%
        mutate(par = ifelse(grepl("drift",iv), "drift_rate", ifelse(grepl("thresh", iv), "threshold", ifelse(grepl("non_decision", iv), "non_decision", NA)))) %>% 
  group_by(dv, par) %>%
  summarise(RsquaredSE = sem(Rsquared),
            Rsquared = mean(Rsquared),
            iv_data = as.character(unique(iv_data)),
            dv_data = as.character(unique(dv_data))) %>%
  rename(iv = par) %>%
  ungroup() %>%
  mutate(dv = as.character(dv)) %>%
  select(dv, iv, Rsquared, RsquaredSE, iv_data, dv_data)
    }
    out = out %>%
      bind_rows(d)
  }
}
p = out %>% 
  mutate(iv = factor(iv, levels = c("drift_rate", "threshold", "non_decision","accuracy", "rt"), labels=c("drift rate", "threshold", "non-decision","accuracy", "rt")),
         dv = factor(dv, levels = c('Drug_Use','Mental_Health','Problem_Drinking','Daily_Smoking','Binge_Drinking','Obesity','Lifetime_Smoking','Unsafe_Drinking','Income_LifeMilestones'), labels = c('Drug Use','Mental Health','Problem Drinking','Daily Smoking','Binge Drinking','Obesity','Lifetime Smoking','Unsafe Drinking','Income/Life Milestones')),
         iv_data = factor(iv_data, levels = c("ez_t1_522_fa_3_scores", "ez_t1_fa_3_scores", "res_clean_test_data_ez", "res_clean_test_data_raw"),
                          labels = c("EZ factors (n=522)", "EZ factors (n=150)", "EZ measures", "Raw measures"))) %>%
  ggplot(aes(iv, Rsquared, fill=iv, alpha=dv_data))+
  geom_bar(stat="identity", position = position_dodge())+
  geom_errorbar(aes(ymin=Rsquared-RsquaredSE, ymax=Rsquared+RsquaredSE, color=iv), position=position_dodge(width=0.9), width=0.1)+
  facet_grid(iv_data~dv, scales='free_x', labeller = label_wrap_gen(width = 2, multi_line = TRUE))+
  theme(legend.title = element_blank(),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        legend.text = element_text(size=16),
        strip.text = element_text(size=16),
        axis.title.y = element_text(size=16),
        axis.text.y= element_text(size=14))+
  xlab("")+
  ylab(expression(R^{2}))+
  scale_alpha_manual(values = c(0.5, 1),
                     breaks = c("demog_fa_scores_t1", "ian_demog_scores"),
                     labels = c("My demog factors", "Ian demog factors"))
  # guides(alpha=FALSE)

ggsave(paste0('pred_dv_data_comparison.', out_device), plot=p, device = out_device, path = fig_path, width = 20, height = 9, units = "in")

Larger figure here

fig_name = 'pred_dv_data_comparison.jpeg'

knitr::include_graphics(paste0(fig_path, fig_name))

2. IV data

Based on the above plot I wondered:
a. Is there something weird about retest sample (n=150)
b. If the factor model for the EZ variables is not good due to linear dependencies between the measures going into the model do the results change if we fit the model on a subset of the EZ variables (specifically condition variables only)

Thus the IV data can vary on a few dimensions:

  • Sample the factor models are based on: The models depicted below are always fit on the whole sample
  • Sample the prediction is done on: Even though all models are fit on the whole sample for prediction I used either all the scores or smaller subsets (retest sample and non-retest sample)
  • Variables that go in to the factor model: Modeling either all EZ variables or just EZ condition variables

In the plot n=150 refers to the retest sample, n=372 subjects who aren’t in the retest sample (non-retest sample)

iv_dfs = c('ez_t1_522_fa_3_scores', 'ez_t1_522_fa_3_scores_t2subs', 'ez_t1_522_fa_3_scores_nont2subs', 'ez_t1_522_fa_3_condition_scores', 'ez_t1_522_fa_3_condition_scores_t2subs', 'ez_t1_522_fa_3_condition_scores_nont2subs', 'res_clean_test_data_ez','res_clean_test_data_ez_522','res_clean_test_data_ez_nont2subs','res_clean_test_data_raw','res_clean_test_data_raw_522','res_clean_test_data_raw_nont2subs' )
dv_dfs = c('demog_fa_scores_t1')

out = data.frame()

for(iv_data in iv_dfs){
  for(dv_data in dv_dfs){
    file_name = paste0(input_path,'prediction/pred_out_', iv_data,'_', dv_data, '.csv')
    
    d = read.csv(file_name) 
    
    if(iv_data %in% c('ez_t1_522_fa_3_scores', 'ez_t1_522_fa_3_scores_t2subs', 'ez_t1_522_fa_3_scores_nont2subs', 'ez_t1_522_fa_3_condition_scores', 'ez_t1_522_fa_3_condition_scores_t2subs', 'ez_t1_522_fa_3_condition_scores_nont2subs')){
      d = d %>%
        mutate(RsquaredSE = RsquaredSD/sqrt(10),
         iv=as.character(iv),
         dv = as.character(dv),
         iv_data = as.character(iv_data),
         dv_data = as.character(dv_data)) %>%
  select(dv, iv, Rsquared, RsquaredSE, iv_data, dv_data)
    }
    
    if(iv_data %in% c("res_clean_test_data_raw_522", "res_clean_test_data_raw", "res_clean_test_data_raw_nont2subs")){
      d = d %>%
        mutate(iv=as.character(iv),
         iv=gsub(".ReflogTr", "",iv),
         iv=gsub(".logTr", "",iv)) %>% 
  left_join(measure_labels %>% select(dv, rt_acc) %>% rename(iv=dv), by="iv") %>%
  group_by(dv, rt_acc) %>%
  summarise(RsquaredSE = sem(Rsquared),
            Rsquared = mean(Rsquared),
            iv_data = as.character(unique(iv_data)),
            dv_data = as.character(unique(dv_data))) %>%
  rename(iv = rt_acc) %>%
  ungroup() %>%
  mutate(dv = as.character(dv)) %>%
  select(dv, iv, Rsquared, RsquaredSE, iv_data, dv_data)
    }
    
    if(iv_data %in% c("res_clean_test_data_ez_522", "res_clean_test_data_ez", "res_clean_test_data_ez_nont2subs")){
      d = d%>%
        mutate(par = ifelse(grepl("drift",iv), "drift_rate", ifelse(grepl("thresh", iv), "threshold", ifelse(grepl("non_decision", iv), "non_decision", NA)))) %>% 
  group_by(dv, par) %>%
  summarise(RsquaredSE = sem(Rsquared),
            Rsquared = mean(Rsquared),
            iv_data = as.character(unique(iv_data)),
            dv_data = as.character(unique(dv_data))) %>%
  rename(iv = par) %>%
  ungroup() %>%
  mutate(dv = as.character(dv)) %>%
  select(dv, iv, Rsquared, RsquaredSE, iv_data, dv_data)
    }
    out = out %>%
      bind_rows(d)
  }
}
p = out %>% 
  mutate(iv = factor(iv, levels = c("drift_rate", "threshold", "non_decision", "accuracy", "rt"), labels=c("drift rate", "threshold", "non-decision","accuracy", "rt")),
         dv = factor(dv, levels = c('Drug_Use','Mental_Health','Problem_Drinking','Daily_Smoking','Binge_Drinking','Obesity','Lifetime_Smoking','Unsafe_Drinking','Income_LifeMilestones'), labels = c('Drug Use','Mental Health','Problem Drinking','Daily Smoking','Binge Drinking','Obesity','Lifetime Smoking','Unsafe Drinking','Income/Life Milestones')),
         iv_data_2 = ifelse(iv_data %in% c('ez_t1_522_fa_3_scores', 'ez_t1_522_fa_3_scores_t2subs', 'ez_t1_522_fa_3_scores_nont2subs'),"EZ all var factors",ifelse(iv_data %in% c('ez_t1_522_fa_3_condition_scores', 'ez_t1_522_fa_3_condition_scores_t2subs', 'ez_t1_522_fa_3_condition_scores_nont2subs'),"EZ cond var factors", ifelse(iv_data %in% c('res_clean_test_data_ez_522', 'res_clean_test_data_ez', 'res_clean_test_data_ez_nont2subs'), "EZ measures", ifelse(iv_data %in% c('res_clean_test_data_raw_522','res_clean_test_data_raw','res_clean_test_data_raw_nont2subs'),"Raw measures",NA)))),
         sample = ifelse(iv_data %in% c('ez_t1_522_fa_3_scores','ez_t1_522_fa_3_condition_scores', 'res_clean_test_data_ez_522','res_clean_test_data_raw_522'),522,ifelse(iv_data %in% c('ez_t1_522_fa_3_scores_nont2subs', 'ez_t1_522_fa_3_condition_scores_nont2subs', 'res_clean_test_data_ez_nont2subs', 'res_clean_test_data_raw_nont2subs'),372, ifelse(iv_data %in% c('ez_t1_522_fa_3_scores_t2subs', 'ez_t1_522_fa_3_condition_scores_t2subs', 'res_clean_test_data_ez', 'res_clean_test_data_raw'),150, NA))),
         sample = factor(sample, levels = c(150, 372, 522), labels = c(150, 372, 522))) %>%
  ggplot(aes(iv, Rsquared, fill=iv, alpha=sample))+
  geom_bar(stat="identity", position = position_dodge())+
  geom_errorbar(aes(ymin=Rsquared-RsquaredSE, ymax=Rsquared+RsquaredSE, color=iv), position=position_dodge(width=0.9), width=0.1)+
  facet_grid(iv_data_2~dv, scales='free_x', labeller = label_wrap_gen(width = 2, multi_line = TRUE))+
  theme(legend.title = element_blank(),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        legend.text = element_text(size=16),
        strip.text = element_text(size=16),
        axis.title.y = element_text(size=16),
        axis.text.y= element_text(size=14))+
  xlab("")+
  ylab(expression(R^{2}))+
  scale_alpha_manual(values = c(0.33,0.66, 1))

ggsave(paste0('pred_iv_data_comparison.', out_device), plot=p, device = out_device, path = fig_path, width = 20, height = 9, units = "in")

Larger figure here

fig_name = 'pred_iv_data_comparison.jpeg'

knitr::include_graphics(paste0(fig_path, fig_name))

LS0tCnRpdGxlOiAnU1JPIERETSBQcmVkaWN0aW9uIGNvbXBhcmlzb24nCm91dHB1dDoKZ2l0aHViX2RvY3VtZW50Ogp0b2M6IHllcwp0b2NfZmxvYXQ6IHllcwotLS0KClRyeWluZyB0byBnZXQgdG8gdGhlIGJvdHRvbSBvZiB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBteSBhbmQgSWFuJ3MgcHJlZGljdGlvbiBhbmFseXNlcy4KClByb2JsZW06IEluIGhpcyBhbmFseXNlcyBJYW4gZm91bmQgdmVyeSBsb3cgY3Jvc3MtdmFsaWRhdGVkICRSXjIkIHZhbHVlcyB3aGVuIHByZWRpY3RpbmcgZGVtb2dyYXBoaWMgZmFjdG9ycyB1c2luZyB0aGUgdGFzayBvbnRvbG9neS4gSW4gbXkgYW5hbHlzZXMgdXNpbmcgZmFjdG9ycyBvZiBFWiBERE0gdmFyaWFibGVzIGFuZCByYXcgUlQncyBhbmQgYWNjdXJhY2llcyBJIGZvdW5kIHJlbGF0aW9uc2hpcHMgdGhhdCB3ZXJlID4wLgoKQXBwcm9hY2g6IE91ciBhbmFseXNlcyBkaWZmZXIgaW4gbXVsdGlwbGUgYXNwZWN0cyBib3RoIGluIHRoZSBwcmVkaWN0ZWQgZGF0YSAoRFYgZGF0YSkgYW5kIHByZWRpY3RvciBkYXRhIChJViBkYXRhKSBzbyB3ZSBjaGVja2VkIGVhY2ggb2YgdGhlbSB0byBmaW5kIHdoZXJlIHRoZSBkaWZmZXJlbmNlIG1heSBsYXkuICAKCiMxLiBEViBkYXRhICAKV2UgYm90aCBjYWxjdWxhdGVkIDkgZmFjdG9yIHNvbHV0aW9ucyBmb3IgdGhlIGRlbW9ncmFwaGljIGl0ZW1zIHNlcGFyYXRlbHkuIG91ciBmYWN0b3Igc2NvcmVzIGFyZSBlc3NlbnRpYWxseSB0aGUgc2FtZSBhcyBjYW4gYmUgc2VlbiBpbiB0aGUgbGFzdCBwbG90IFtoZXJlXShodHRwczovL3plbmthdmkuZ2l0aHViLmlvL1NST19ERE1fQW5hbHlzZXMvb3V0cHV0L3JlcG9ydHMvRGVtb2dyYXBoaWNGYWN0b3JzLm5iLmh0bWwpLiAgCgpTdGlsbCwgY2hlY2tlZCB3aGV0aGVyIHRoZXJlIHdlcmUgYW55IGRpZmZlcmVuY2VzIHByZWRpY3RpbmcgaGlzIG9yIG15IGZhY3RvciBzY29yZXMuIAoKVGhlIHBsb3QgYmVsb3cgc3VnZ2VzdHMgIAotIFRoZXJlIGFyZSBubyBzeXN0ZW1hdGljIGRpZmZlcmVuY2VzIGRlcGVuZGluZyBvbiB0aGUgRFYgZGF0YSAgCi0gVGhlIGxhcmdlc3QgZGlmZmVyZW5jZSBpcyBiZXR3ZWVuIHByZWRpY3RpbmcgdXNpbmcgbj01MjIgb3Igbj0xNTAgIAotIFJhdyBtZWFzdXJlcyBzZWVtIHRvIGhhdmUgc29tZSA+MCBhc3NvY2lhdGlvbiB0b28gIAoKYGBge3J9CmhlbHBlcl9mdW5jX3BhdGggPSAnaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3plbmthdmkvU1JPX1JldGVzdF9BbmFseXNlcy9tYXN0ZXIvY29kZS9oZWxwZXJfZnVuY3Rpb25zLycKCmV2YWwocGFyc2UodGV4dCA9IGdldFVSTChwYXN0ZTAoaGVscGVyX2Z1bmNfcGF0aCwnc2VtLlInKSwgc3NsLnZlcmlmeXBlZXIgPSBGQUxTRSkpKQoKZGRtX3dvcmtzcGFjZV9zY3JpcHRzID0gJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS96ZW5rYXZpL1NST19ERE1fQW5hbHlzZXMvbWFzdGVyL2NvZGUvd29ya3NwYWNlX3NjcmlwdHMvJwoKZXZhbChwYXJzZSh0ZXh0ID0gZ2V0VVJMKHBhc3RlMChkZG1fd29ya3NwYWNlX3NjcmlwdHMsJ2RkbV9tZWFzdXJlX2xhYmVscy5SJyksIHNzbC52ZXJpZnlwZWVyID0gRkFMU0UpKSkKCmlucHV0X3BhdGg9Jy9Vc2Vycy96ZXluZXBlbmthdmkvRHJvcGJveC9Qb2xkcmFja0xhYi9TUk9fRERNX0FuYWx5c2VzL2lucHV0LycKCm91dF9kZXZpY2UgPSAianBlZyIKCmZpZ19wYXRoID0gJy9Vc2Vycy96ZXluZXBlbmthdmkvRHJvcGJveC9Qb2xkcmFja0xhYi9TUk9fRERNX0FuYWx5c2VzL291dHB1dC9maWd1cmVzLycKYGBgCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQppdl9kZnMgPSBjKCJlel90MV81MjJfZmFfM19zY29yZXMiLCAiZXpfdDFfZmFfM19zY29yZXMiLCAicmVzX2NsZWFuX3Rlc3RfZGF0YV9yYXciLCAicmVzX2NsZWFuX3Rlc3RfZGF0YV9leiIpCmR2X2RmcyA9IGMoJ2lhbl9kZW1vZ19zY29yZXMnLCAnZGVtb2dfZmFfc2NvcmVzX3QxJykKCm91dCA9IGRhdGEuZnJhbWUoKQoKZm9yKGl2X2RhdGEgaW4gaXZfZGZzKXsKICBmb3IoZHZfZGF0YSBpbiBkdl9kZnMpewogICAgZmlsZV9uYW1lID0gcGFzdGUwKGlucHV0X3BhdGgsJ3ByZWRpY3Rpb24vcHJlZF9vdXRfJywgaXZfZGF0YSwnXycsIGR2X2RhdGEsICcuY3N2JykKICAgIAogICAgZCA9IHJlYWQuY3N2KGZpbGVfbmFtZSkgCiAgICAKICAgIGlmKGl2X2RhdGEgJWluJSBjKCJlel90MV81MjJfZmFfM19zY29yZXMiLCAiZXpfdDFfZmFfM19zY29yZXMiKSl7CiAgICAgIGQgPSBkICU+JQogICAgICAgIG11dGF0ZShSc3F1YXJlZFNFID0gUnNxdWFyZWRTRC9zcXJ0KDEwKSwKICAgICAgICAgaXY9YXMuY2hhcmFjdGVyKGl2KSwKICAgICAgICAgZHYgPSBhcy5jaGFyYWN0ZXIoZHYpLAogICAgICAgICBpdl9kYXRhID0gYXMuY2hhcmFjdGVyKGl2X2RhdGEpLAogICAgICAgICBkdl9kYXRhID0gYXMuY2hhcmFjdGVyKGR2X2RhdGEpKSAlPiUKICBzZWxlY3QoZHYsIGl2LCBSc3F1YXJlZCwgUnNxdWFyZWRTRSwgaXZfZGF0YSwgZHZfZGF0YSkKICAgIH0KICAgIAogICAgaWYoaXZfZGF0YSA9PSJyZXNfY2xlYW5fdGVzdF9kYXRhX3JhdyIpewogICAgICBkID0gZCAlPiUKICAgICAgICBtdXRhdGUoaXY9YXMuY2hhcmFjdGVyKGl2KSwKICAgICAgICAgaXY9Z3N1YigiLlJlZmxvZ1RyIiwgIiIsaXYpLAogICAgICAgICBpdj1nc3ViKCIubG9nVHIiLCAiIixpdikpICU+JSAKICBsZWZ0X2pvaW4obWVhc3VyZV9sYWJlbHMgJT4lIHNlbGVjdChkdiwgcnRfYWNjKSAlPiUgcmVuYW1lKGl2PWR2KSwgYnk9Iml2IikgJT4lCiAgZ3JvdXBfYnkoZHYsIHJ0X2FjYykgJT4lCiAgc3VtbWFyaXNlKFJzcXVhcmVkU0UgPSBzZW0oUnNxdWFyZWQpLAogICAgICAgICAgICBSc3F1YXJlZCA9IG1lYW4oUnNxdWFyZWQpLAogICAgICAgICAgICBpdl9kYXRhID0gYXMuY2hhcmFjdGVyKHVuaXF1ZShpdl9kYXRhKSksCiAgICAgICAgICAgIGR2X2RhdGEgPSBhcy5jaGFyYWN0ZXIodW5pcXVlKGR2X2RhdGEpKSkgJT4lCiAgcmVuYW1lKGl2ID0gcnRfYWNjKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKGR2ID0gYXMuY2hhcmFjdGVyKGR2KSkgJT4lCiAgc2VsZWN0KGR2LCBpdiwgUnNxdWFyZWQsIFJzcXVhcmVkU0UsIGl2X2RhdGEsIGR2X2RhdGEpCiAgICB9CiAgICAKICAgIGlmKGl2X2RhdGEgPT0gInJlc19jbGVhbl90ZXN0X2RhdGFfZXoiKXsKICAgICAgZCA9IGQlPiUKICAgICAgICBtdXRhdGUocGFyID0gaWZlbHNlKGdyZXBsKCJkcmlmdCIsaXYpLCAiZHJpZnRfcmF0ZSIsIGlmZWxzZShncmVwbCgidGhyZXNoIiwgaXYpLCAidGhyZXNob2xkIiwgaWZlbHNlKGdyZXBsKCJub25fZGVjaXNpb24iLCBpdiksICJub25fZGVjaXNpb24iLCBOQSkpKSkgJT4lIAogIGdyb3VwX2J5KGR2LCBwYXIpICU+JQogIHN1bW1hcmlzZShSc3F1YXJlZFNFID0gc2VtKFJzcXVhcmVkKSwKICAgICAgICAgICAgUnNxdWFyZWQgPSBtZWFuKFJzcXVhcmVkKSwKICAgICAgICAgICAgaXZfZGF0YSA9IGFzLmNoYXJhY3Rlcih1bmlxdWUoaXZfZGF0YSkpLAogICAgICAgICAgICBkdl9kYXRhID0gYXMuY2hhcmFjdGVyKHVuaXF1ZShkdl9kYXRhKSkpICU+JQogIHJlbmFtZShpdiA9IHBhcikgJT4lCiAgdW5ncm91cCgpICU+JQogIG11dGF0ZShkdiA9IGFzLmNoYXJhY3RlcihkdikpICU+JQogIHNlbGVjdChkdiwgaXYsIFJzcXVhcmVkLCBSc3F1YXJlZFNFLCBpdl9kYXRhLCBkdl9kYXRhKQogICAgfQogICAgb3V0ID0gb3V0ICU+JQogICAgICBiaW5kX3Jvd3MoZCkKICB9Cn0KYGBgCgpgYGB7cn0KcCA9IG91dCAlPiUgCiAgbXV0YXRlKGl2ID0gZmFjdG9yKGl2LCBsZXZlbHMgPSBjKCJkcmlmdF9yYXRlIiwgInRocmVzaG9sZCIsICJub25fZGVjaXNpb24iLCJhY2N1cmFjeSIsICJydCIpLCBsYWJlbHM9YygiZHJpZnQgcmF0ZSIsICJ0aHJlc2hvbGQiLCAibm9uLWRlY2lzaW9uIiwiYWNjdXJhY3kiLCAicnQiKSksCiAgICAgICAgIGR2ID0gZmFjdG9yKGR2LCBsZXZlbHMgPSBjKCdEcnVnX1VzZScsJ01lbnRhbF9IZWFsdGgnLCdQcm9ibGVtX0RyaW5raW5nJywnRGFpbHlfU21va2luZycsJ0JpbmdlX0RyaW5raW5nJywnT2Jlc2l0eScsJ0xpZmV0aW1lX1Ntb2tpbmcnLCdVbnNhZmVfRHJpbmtpbmcnLCdJbmNvbWVfTGlmZU1pbGVzdG9uZXMnKSwgbGFiZWxzID0gYygnRHJ1ZyBVc2UnLCdNZW50YWwgSGVhbHRoJywnUHJvYmxlbSBEcmlua2luZycsJ0RhaWx5IFNtb2tpbmcnLCdCaW5nZSBEcmlua2luZycsJ09iZXNpdHknLCdMaWZldGltZSBTbW9raW5nJywnVW5zYWZlIERyaW5raW5nJywnSW5jb21lL0xpZmUgTWlsZXN0b25lcycpKSwKICAgICAgICAgaXZfZGF0YSA9IGZhY3Rvcihpdl9kYXRhLCBsZXZlbHMgPSBjKCJlel90MV81MjJfZmFfM19zY29yZXMiLCAiZXpfdDFfZmFfM19zY29yZXMiLCAicmVzX2NsZWFuX3Rlc3RfZGF0YV9leiIsICJyZXNfY2xlYW5fdGVzdF9kYXRhX3JhdyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkVaIGZhY3RvcnMgKG49NTIyKSIsICJFWiBmYWN0b3JzIChuPTE1MCkiLCAiRVogbWVhc3VyZXMiLCAiUmF3IG1lYXN1cmVzIikpKSAlPiUKICBnZ3Bsb3QoYWVzKGl2LCBSc3F1YXJlZCwgZmlsbD1pdiwgYWxwaGE9ZHZfZGF0YSkpKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgpKSsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPVJzcXVhcmVkLVJzcXVhcmVkU0UsIHltYXg9UnNxdWFyZWQrUnNxdWFyZWRTRSwgY29sb3I9aXYpLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjkpLCB3aWR0aD0wLjEpKwogIGZhY2V0X2dyaWQoaXZfZGF0YX5kdiwgc2NhbGVzPSdmcmVlX3gnLCBsYWJlbGxlciA9IGxhYmVsX3dyYXBfZ2VuKHdpZHRoID0gMiwgbXVsdGlfbGluZSA9IFRSVUUpKSsKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLAogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLAogICAgICAgIGF4aXMudGV4dC55PSBlbGVtZW50X3RleHQoc2l6ZT0xNCkpKwogIHhsYWIoIiIpKwogIHlsYWIoZXhwcmVzc2lvbihSXnsyfSkpKwogIHNjYWxlX2FscGhhX21hbnVhbCh2YWx1ZXMgPSBjKDAuNSwgMSksCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoImRlbW9nX2ZhX3Njb3Jlc190MSIsICJpYW5fZGVtb2dfc2NvcmVzIiksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk15IGRlbW9nIGZhY3RvcnMiLCAiSWFuIGRlbW9nIGZhY3RvcnMiKSkKICAjIGd1aWRlcyhhbHBoYT1GQUxTRSkKCmdnc2F2ZShwYXN0ZTAoJ3ByZWRfZHZfZGF0YV9jb21wYXJpc29uLicsIG91dF9kZXZpY2UpLCBwbG90PXAsIGRldmljZSA9IG91dF9kZXZpY2UsIHBhdGggPSBmaWdfcGF0aCwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gOSwgdW5pdHMgPSAiaW4iKQpgYGAKCkxhcmdlciBmaWd1cmUgW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS96ZW5rYXZpL1NST19ERE1fQW5hbHlzZXMvYmxvYi9tYXN0ZXIvb3V0cHV0L2ZpZ3VyZXMvcHJlZF9kdl9kYXRhX2NvbXBhcmlzb24uanBlZykKCmBgYHtyfQpmaWdfbmFtZSA9ICdwcmVkX2R2X2RhdGFfY29tcGFyaXNvbi5qcGVnJwoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MocGFzdGUwKGZpZ19wYXRoLCBmaWdfbmFtZSkpCmBgYAoKIzIuIElWIGRhdGEKCkJhc2VkIG9uIHRoZSBhYm92ZSBwbG90IEkgd29uZGVyZWQ6ICAKYS4gSXMgdGhlcmUgc29tZXRoaW5nIHdlaXJkIGFib3V0IHJldGVzdCBzYW1wbGUgKG49MTUwKSAgCmIuIElmIHRoZSBmYWN0b3IgbW9kZWwgZm9yIHRoZSBFWiB2YXJpYWJsZXMgaXMgbm90IGdvb2QgZHVlIHRvIGxpbmVhciBkZXBlbmRlbmNpZXMgYmV0d2VlbiB0aGUgbWVhc3VyZXMgZ29pbmcgaW50byB0aGUgbW9kZWwgZG8gdGhlIHJlc3VsdHMgY2hhbmdlIGlmIHdlIGZpdCB0aGUgbW9kZWwgb24gYSBzdWJzZXQgb2YgdGhlIEVaIHZhcmlhYmxlcyAoc3BlY2lmaWNhbGx5IGNvbmRpdGlvbiB2YXJpYWJsZXMgb25seSkgIAoKVGh1cyB0aGUgSVYgZGF0YSBjYW4gdmFyeSBvbiBhIGZldyBkaW1lbnNpb25zOiAgCgotIFNhbXBsZSB0aGUgZmFjdG9yIG1vZGVscyBhcmUgYmFzZWQgb246IFRoZSBtb2RlbHMgZGVwaWN0ZWQgYmVsb3cgYXJlIGFsd2F5cyBmaXQgb24gdGhlIHdob2xlIHNhbXBsZSAKLSBTYW1wbGUgdGhlIHByZWRpY3Rpb24gaXMgZG9uZSBvbjogRXZlbiB0aG91Z2ggYWxsIG1vZGVscyBhcmUgZml0IG9uIHRoZSB3aG9sZSBzYW1wbGUgZm9yIHByZWRpY3Rpb24gSSB1c2VkIGVpdGhlciBhbGwgdGhlIHNjb3JlcyBvciBzbWFsbGVyIHN1YnNldHMgKHJldGVzdCBzYW1wbGUgYW5kIG5vbi1yZXRlc3Qgc2FtcGxlKQotIFZhcmlhYmxlcyB0aGF0IGdvIGluIHRvIHRoZSBmYWN0b3IgbW9kZWw6IE1vZGVsaW5nIGVpdGhlciBhbGwgRVogdmFyaWFibGVzIG9yIGp1c3QgRVogY29uZGl0aW9uIHZhcmlhYmxlcwoKSW4gdGhlIHBsb3Qgbj0xNTAgcmVmZXJzIHRvIHRoZSByZXRlc3Qgc2FtcGxlLCBuPTM3MiBzdWJqZWN0cyB3aG8gYXJlbid0IGluIHRoZSByZXRlc3Qgc2FtcGxlIChub24tcmV0ZXN0IHNhbXBsZSkKCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQppdl9kZnMgPSBjKCdlel90MV81MjJfZmFfM19zY29yZXMnLCAnZXpfdDFfNTIyX2ZhXzNfc2NvcmVzX3Qyc3VicycsICdlel90MV81MjJfZmFfM19zY29yZXNfbm9udDJzdWJzJywgJ2V6X3QxXzUyMl9mYV8zX2NvbmRpdGlvbl9zY29yZXMnLCAnZXpfdDFfNTIyX2ZhXzNfY29uZGl0aW9uX3Njb3Jlc190MnN1YnMnLCAnZXpfdDFfNTIyX2ZhXzNfY29uZGl0aW9uX3Njb3Jlc19ub250MnN1YnMnLCAncmVzX2NsZWFuX3Rlc3RfZGF0YV9leicsJ3Jlc19jbGVhbl90ZXN0X2RhdGFfZXpfNTIyJywncmVzX2NsZWFuX3Rlc3RfZGF0YV9lel9ub250MnN1YnMnLCdyZXNfY2xlYW5fdGVzdF9kYXRhX3JhdycsJ3Jlc19jbGVhbl90ZXN0X2RhdGFfcmF3XzUyMicsJ3Jlc19jbGVhbl90ZXN0X2RhdGFfcmF3X25vbnQyc3VicycgKQpkdl9kZnMgPSBjKCdkZW1vZ19mYV9zY29yZXNfdDEnKQoKb3V0ID0gZGF0YS5mcmFtZSgpCgpmb3IoaXZfZGF0YSBpbiBpdl9kZnMpewogIGZvcihkdl9kYXRhIGluIGR2X2Rmcyl7CiAgICBmaWxlX25hbWUgPSBwYXN0ZTAoaW5wdXRfcGF0aCwncHJlZGljdGlvbi9wcmVkX291dF8nLCBpdl9kYXRhLCdfJywgZHZfZGF0YSwgJy5jc3YnKQogICAgCiAgICBkID0gcmVhZC5jc3YoZmlsZV9uYW1lKSAKICAgIAogICAgaWYoaXZfZGF0YSAlaW4lIGMoJ2V6X3QxXzUyMl9mYV8zX3Njb3JlcycsICdlel90MV81MjJfZmFfM19zY29yZXNfdDJzdWJzJywgJ2V6X3QxXzUyMl9mYV8zX3Njb3Jlc19ub250MnN1YnMnLCAnZXpfdDFfNTIyX2ZhXzNfY29uZGl0aW9uX3Njb3JlcycsICdlel90MV81MjJfZmFfM19jb25kaXRpb25fc2NvcmVzX3Qyc3VicycsICdlel90MV81MjJfZmFfM19jb25kaXRpb25fc2NvcmVzX25vbnQyc3VicycpKXsKICAgICAgZCA9IGQgJT4lCiAgICAgICAgbXV0YXRlKFJzcXVhcmVkU0UgPSBSc3F1YXJlZFNEL3NxcnQoMTApLAogICAgICAgICBpdj1hcy5jaGFyYWN0ZXIoaXYpLAogICAgICAgICBkdiA9IGFzLmNoYXJhY3RlcihkdiksCiAgICAgICAgIGl2X2RhdGEgPSBhcy5jaGFyYWN0ZXIoaXZfZGF0YSksCiAgICAgICAgIGR2X2RhdGEgPSBhcy5jaGFyYWN0ZXIoZHZfZGF0YSkpICU+JQogIHNlbGVjdChkdiwgaXYsIFJzcXVhcmVkLCBSc3F1YXJlZFNFLCBpdl9kYXRhLCBkdl9kYXRhKQogICAgfQogICAgCiAgICBpZihpdl9kYXRhICVpbiUgYygicmVzX2NsZWFuX3Rlc3RfZGF0YV9yYXdfNTIyIiwgInJlc19jbGVhbl90ZXN0X2RhdGFfcmF3IiwgInJlc19jbGVhbl90ZXN0X2RhdGFfcmF3X25vbnQyc3VicyIpKXsKICAgICAgZCA9IGQgJT4lCiAgICAgICAgbXV0YXRlKGl2PWFzLmNoYXJhY3RlcihpdiksCiAgICAgICAgIGl2PWdzdWIoIi5SZWZsb2dUciIsICIiLGl2KSwKICAgICAgICAgaXY9Z3N1YigiLmxvZ1RyIiwgIiIsaXYpKSAlPiUgCiAgbGVmdF9qb2luKG1lYXN1cmVfbGFiZWxzICU+JSBzZWxlY3QoZHYsIHJ0X2FjYykgJT4lIHJlbmFtZShpdj1kdiksIGJ5PSJpdiIpICU+JQogIGdyb3VwX2J5KGR2LCBydF9hY2MpICU+JQogIHN1bW1hcmlzZShSc3F1YXJlZFNFID0gc2VtKFJzcXVhcmVkKSwKICAgICAgICAgICAgUnNxdWFyZWQgPSBtZWFuKFJzcXVhcmVkKSwKICAgICAgICAgICAgaXZfZGF0YSA9IGFzLmNoYXJhY3Rlcih1bmlxdWUoaXZfZGF0YSkpLAogICAgICAgICAgICBkdl9kYXRhID0gYXMuY2hhcmFjdGVyKHVuaXF1ZShkdl9kYXRhKSkpICU+JQogIHJlbmFtZShpdiA9IHJ0X2FjYykgJT4lCiAgdW5ncm91cCgpICU+JQogIG11dGF0ZShkdiA9IGFzLmNoYXJhY3RlcihkdikpICU+JQogIHNlbGVjdChkdiwgaXYsIFJzcXVhcmVkLCBSc3F1YXJlZFNFLCBpdl9kYXRhLCBkdl9kYXRhKQogICAgfQogICAgCiAgICBpZihpdl9kYXRhICVpbiUgYygicmVzX2NsZWFuX3Rlc3RfZGF0YV9lel81MjIiLCAicmVzX2NsZWFuX3Rlc3RfZGF0YV9leiIsICJyZXNfY2xlYW5fdGVzdF9kYXRhX2V6X25vbnQyc3VicyIpKXsKICAgICAgZCA9IGQlPiUKICAgICAgICBtdXRhdGUocGFyID0gaWZlbHNlKGdyZXBsKCJkcmlmdCIsaXYpLCAiZHJpZnRfcmF0ZSIsIGlmZWxzZShncmVwbCgidGhyZXNoIiwgaXYpLCAidGhyZXNob2xkIiwgaWZlbHNlKGdyZXBsKCJub25fZGVjaXNpb24iLCBpdiksICJub25fZGVjaXNpb24iLCBOQSkpKSkgJT4lIAogIGdyb3VwX2J5KGR2LCBwYXIpICU+JQogIHN1bW1hcmlzZShSc3F1YXJlZFNFID0gc2VtKFJzcXVhcmVkKSwKICAgICAgICAgICAgUnNxdWFyZWQgPSBtZWFuKFJzcXVhcmVkKSwKICAgICAgICAgICAgaXZfZGF0YSA9IGFzLmNoYXJhY3Rlcih1bmlxdWUoaXZfZGF0YSkpLAogICAgICAgICAgICBkdl9kYXRhID0gYXMuY2hhcmFjdGVyKHVuaXF1ZShkdl9kYXRhKSkpICU+JQogIHJlbmFtZShpdiA9IHBhcikgJT4lCiAgdW5ncm91cCgpICU+JQogIG11dGF0ZShkdiA9IGFzLmNoYXJhY3RlcihkdikpICU+JQogIHNlbGVjdChkdiwgaXYsIFJzcXVhcmVkLCBSc3F1YXJlZFNFLCBpdl9kYXRhLCBkdl9kYXRhKQogICAgfQogICAgb3V0ID0gb3V0ICU+JQogICAgICBiaW5kX3Jvd3MoZCkKICB9Cn0KYGBgCgpgYGB7cn0KcCA9IG91dCAlPiUgCiAgbXV0YXRlKGl2ID0gZmFjdG9yKGl2LCBsZXZlbHMgPSBjKCJkcmlmdF9yYXRlIiwgInRocmVzaG9sZCIsICJub25fZGVjaXNpb24iLCAiYWNjdXJhY3kiLCAicnQiKSwgbGFiZWxzPWMoImRyaWZ0IHJhdGUiLCAidGhyZXNob2xkIiwgIm5vbi1kZWNpc2lvbiIsImFjY3VyYWN5IiwgInJ0IikpLAogICAgICAgICBkdiA9IGZhY3RvcihkdiwgbGV2ZWxzID0gYygnRHJ1Z19Vc2UnLCdNZW50YWxfSGVhbHRoJywnUHJvYmxlbV9Ecmlua2luZycsJ0RhaWx5X1Ntb2tpbmcnLCdCaW5nZV9Ecmlua2luZycsJ09iZXNpdHknLCdMaWZldGltZV9TbW9raW5nJywnVW5zYWZlX0RyaW5raW5nJywnSW5jb21lX0xpZmVNaWxlc3RvbmVzJyksIGxhYmVscyA9IGMoJ0RydWcgVXNlJywnTWVudGFsIEhlYWx0aCcsJ1Byb2JsZW0gRHJpbmtpbmcnLCdEYWlseSBTbW9raW5nJywnQmluZ2UgRHJpbmtpbmcnLCdPYmVzaXR5JywnTGlmZXRpbWUgU21va2luZycsJ1Vuc2FmZSBEcmlua2luZycsJ0luY29tZS9MaWZlIE1pbGVzdG9uZXMnKSksCiAgICAgICAgIGl2X2RhdGFfMiA9IGlmZWxzZShpdl9kYXRhICVpbiUgYygnZXpfdDFfNTIyX2ZhXzNfc2NvcmVzJywgJ2V6X3QxXzUyMl9mYV8zX3Njb3Jlc190MnN1YnMnLCAnZXpfdDFfNTIyX2ZhXzNfc2NvcmVzX25vbnQyc3VicycpLCJFWiBhbGwgdmFyIGZhY3RvcnMiLGlmZWxzZShpdl9kYXRhICVpbiUgYygnZXpfdDFfNTIyX2ZhXzNfY29uZGl0aW9uX3Njb3JlcycsICdlel90MV81MjJfZmFfM19jb25kaXRpb25fc2NvcmVzX3Qyc3VicycsICdlel90MV81MjJfZmFfM19jb25kaXRpb25fc2NvcmVzX25vbnQyc3VicycpLCJFWiBjb25kIHZhciBmYWN0b3JzIiwgaWZlbHNlKGl2X2RhdGEgJWluJSBjKCdyZXNfY2xlYW5fdGVzdF9kYXRhX2V6XzUyMicsICdyZXNfY2xlYW5fdGVzdF9kYXRhX2V6JywgJ3Jlc19jbGVhbl90ZXN0X2RhdGFfZXpfbm9udDJzdWJzJyksICJFWiBtZWFzdXJlcyIsIGlmZWxzZShpdl9kYXRhICVpbiUgYygncmVzX2NsZWFuX3Rlc3RfZGF0YV9yYXdfNTIyJywncmVzX2NsZWFuX3Rlc3RfZGF0YV9yYXcnLCdyZXNfY2xlYW5fdGVzdF9kYXRhX3Jhd19ub250MnN1YnMnKSwiUmF3IG1lYXN1cmVzIixOQSkpKSksCiAgICAgICAgIHNhbXBsZSA9IGlmZWxzZShpdl9kYXRhICVpbiUgYygnZXpfdDFfNTIyX2ZhXzNfc2NvcmVzJywnZXpfdDFfNTIyX2ZhXzNfY29uZGl0aW9uX3Njb3JlcycsICdyZXNfY2xlYW5fdGVzdF9kYXRhX2V6XzUyMicsJ3Jlc19jbGVhbl90ZXN0X2RhdGFfcmF3XzUyMicpLDUyMixpZmVsc2UoaXZfZGF0YSAlaW4lIGMoJ2V6X3QxXzUyMl9mYV8zX3Njb3Jlc19ub250MnN1YnMnLCAnZXpfdDFfNTIyX2ZhXzNfY29uZGl0aW9uX3Njb3Jlc19ub250MnN1YnMnLCAncmVzX2NsZWFuX3Rlc3RfZGF0YV9lel9ub250MnN1YnMnLCAncmVzX2NsZWFuX3Rlc3RfZGF0YV9yYXdfbm9udDJzdWJzJyksMzcyLCBpZmVsc2UoaXZfZGF0YSAlaW4lIGMoJ2V6X3QxXzUyMl9mYV8zX3Njb3Jlc190MnN1YnMnLCAnZXpfdDFfNTIyX2ZhXzNfY29uZGl0aW9uX3Njb3Jlc190MnN1YnMnLCAncmVzX2NsZWFuX3Rlc3RfZGF0YV9leicsICdyZXNfY2xlYW5fdGVzdF9kYXRhX3JhdycpLDE1MCwgTkEpKSksCiAgICAgICAgIHNhbXBsZSA9IGZhY3RvcihzYW1wbGUsIGxldmVscyA9IGMoMTUwLCAzNzIsIDUyMiksIGxhYmVscyA9IGMoMTUwLCAzNzIsIDUyMikpKSAlPiUKICBnZ3Bsb3QoYWVzKGl2LCBSc3F1YXJlZCwgZmlsbD1pdiwgYWxwaGE9c2FtcGxlKSkrCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKCkpKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49UnNxdWFyZWQtUnNxdWFyZWRTRSwgeW1heD1Sc3F1YXJlZCtSc3F1YXJlZFNFLCBjb2xvcj1pdiksIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuOSksIHdpZHRoPTAuMSkrCiAgZmFjZXRfZ3JpZChpdl9kYXRhXzJ+ZHYsIHNjYWxlcz0nZnJlZV94JywgbGFiZWxsZXIgPSBsYWJlbF93cmFwX2dlbih3aWR0aCA9IDIsIG11bHRpX2xpbmUgPSBUUlVFKSkrCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwKICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwKICAgICAgICBheGlzLnRleHQueT0gZWxlbWVudF90ZXh0KHNpemU9MTQpKSsKICB4bGFiKCIiKSsKICB5bGFiKGV4cHJlc3Npb24oUl57Mn0pKSsKICBzY2FsZV9hbHBoYV9tYW51YWwodmFsdWVzID0gYygwLjMzLDAuNjYsIDEpKQoKZ2dzYXZlKHBhc3RlMCgncHJlZF9pdl9kYXRhX2NvbXBhcmlzb24uJywgb3V0X2RldmljZSksIHBsb3Q9cCwgZGV2aWNlID0gb3V0X2RldmljZSwgcGF0aCA9IGZpZ19wYXRoLCB3aWR0aCA9IDIwLCBoZWlnaHQgPSA5LCB1bml0cyA9ICJpbiIpCmBgYAoKTGFyZ2VyIGZpZ3VyZSBbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL3plbmthdmkvU1JPX0RETV9BbmFseXNlcy9ibG9iL21hc3Rlci9vdXRwdXQvZmlndXJlcy9wcmVkX2l2X2RhdGFfY29tcGFyaXNvbi5qcGVnKQoKYGBge3J9CmZpZ19uYW1lID0gJ3ByZWRfaXZfZGF0YV9jb21wYXJpc29uLmpwZWcnCgprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhwYXN0ZTAoZmlnX3BhdGgsIGZpZ19uYW1lKSkKYGBgCg==